package mnet

import "time"

/*
 * mnet client
 */

type mClient struct {
	session    ISession
	codec      ICodec
	attach     interface{}
	remoteAddr string
}

// newClient create a client.
func newClient(remoteAddr string,
	session ISession, codec ICodec,
	attach interface{},
) IClient {
	if session == nil {
		panic("session is nil")
	}

	if codec == nil {
		panic("codec is nil")
	}

	client := &mClient{
		session:    session,
		codec:      codec,
		attach:     attach,
		remoteAddr: remoteAddr,
	}
	return client
}

// Async connect to remote server with callback.
func (mc *mClient) AsynConnect(connErrCallback func()) bool {
	connEvt := dealerEvent{
		dealType: netDealerEventConnection,
		connEvent: connectEvent{
			connAddr:    mc.remoteAddr,
			session:     mc.session,
			codec:       mc.codec,
			connErrCall: connErrCallback,
		},
	}
	return GetNetInstance().addDealerEvent(connEvt)
}

// Async connect to remote server without callback(nil)
func (mc *mClient) StartConnect() bool {
	return mc.AsynConnect(nil)
}

// Sync connect to remote server.
func (mc *mClient) SyncConnect() bool {
	return GetNetInstance().syncDial(mc.remoteAddr, mc.session, mc.codec)
}

// GetAttach gets attach.
func (mc *mClient) GetAttach() interface{} {
	return mc.attach
}

// try to connect peer server until it is connected.
func (mc *mClient) TryToConnect() {
	go func() {
		for {
			if mc.SyncConnect() {
				break
			}
			time.Sleep(5 * time.Second)
		}
	}()
}
